Шаг 4 - Изменение кода рисования.

В коде рисования Вы будете использовать функции sin и cos чтобы вычислить точки многоугольника. Для использования этих функций необходимо включение math.h в PolyCtl.h:

#include <math.h>
#include "resource.h"       // main symbols

Внимание только для Release builds. Когда ATL COM AppWizard генерирует проект задана по умолчанию макродиректива _ATL_MIN_CRT. Эта макрокоманда определена так, чтобы не использовать C Run-Time Library в вашем коде если Вы не нуждаетесь в ней. Элемент управления многоугольник нуждается в коде C Run-Time Library чтобы инициализировать функции работы с плавающей запятой. Следовательно Вы должны удалить _ATL_MIN_CRT макрокоманду если Вы хотите формировать Release версию. Чтобы удалить макрокоманду нажмите Settings в меню Project. В Settings For: раскрывающимся списке выберите Multiple Configurations. В Select project configuration(s) to modify диалоговом окне которое появиться нажмите переключатели для всех четырех Release версий, затем нажмите OK. На вкладке C/C++ выберите General категорию, затем удалите _ATL_MIN_CRT из окна редактирования определений (definitions) препроцессора.

Как только точки многоугольника вычислены Вы должны их сохранять. Добавьте массив типа POINT в конец определения класса PolyCtl.h:

   OLE_COLOR m_clrFillColor;
   short m_nSides;
   POINT m_arrPoint[100];

Теперь измените функцию OnDraw в PolyCtl.h как в коде ниже. Обратите внимание что Вы удаляете обращения к функциям Rectangle и DrawText. Вы также явно получаете и выбираете черную и белую кисть. Если окно не Ваше собственное Вы не можете делать предположения относительно контекста устройства в котором вы будете рисовать.

Завершенный OnDraw выглядит следующим образом:

HRESULT CPolyCtl::OnDraw(ATL_DRAWINFO& di)
{
   RECT& rc = *(RECT*)di.prcBounds;
   HDC hdc  = di.hdcDraw;

   COLORREF    colFore;
   HBRUSH      hOldBrush, hBrush;
   HPEN        hOldPen, hPen;

   // Translate m_colFore into a COLORREF type
   OleTranslateColor(m_clrFillColor, NULL, &colFore);

   // Create and select the colors to draw the circle
   hPen = (HPEN)GetStockObject(BLACK_PEN);
   hOldPen = (HPEN)SelectObject(hdc, hPen);
   hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
   hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);

   Ellipse(hdc, rc.left, rc.top, rc.right, rc.bottom);

   // Create and select the brush that will be used to fill the polygon
   hBrush    = CreateSolidBrush(colFore);
   SelectObject(hdc, hBrush);

   CalcPoints(rc);
   Polygon(hdc, &m_arrPoint[0], m_nSides);

   // Select back the old pen and brush and delete the brush we created
   SelectObject(hdc, hOldPen);
   SelectObject(hdc, hOldBrush);
   DeleteObject(hBrush);

   return S_OK;
}

Вы теперь должны добавить функцию с именем CalcPoints которая вычислит координаты пересечений линий. Эти вычисления будут основаны на переменной RECT которая передана в функцию. Сначала Вы должны добавить описание CalcPoints в общий раздел для класса IPolyCtl в PolyCtl.h:

void    CalcPoints(const RECT& rc);

Общий раздел класса IPolyCtl должен теперь выглядеть следующим образом:

// IPolyCtl
public:
   STDMETHOD(get_Sides)(/*[out, retval]*/ short *newVal);
   STDMETHOD(put_Sides)(/*[in]*/ short newVal);
   void    CalcPoints(const RECT& rc);

Затем добавьте реализацию функции CalcPoints в конец PolyCtl.cpp файла:

void CPolyCtl::CalcPoints(const RECT& rc)
{
   const double pi = 3.14159265358979;
   POINT   ptCenter;
   double  dblRadiusx = (rc.right - rc.left) / 2;
   double  dblRadiusy = (rc.bottom - rc.top) / 2;
   double  dblAngle = 3 * pi / 2;          // Start at the top
   double  dblDiff  = 2 * pi / m_nSides;   // Angle each side will make
   ptCenter.x = (rc.left + rc.right) / 2;
   ptCenter.y = (rc.top + rc.bottom) / 2;

   // Calculate the points for each side
   for (int i = 0; i < m_nSides; i++)
   {
      m_arrPoint[i].x = (long)(dblRadiusx * cos(dblAngle) + ptCenter.x + 0.5);
      m_arrPoint[i].y = (long)(dblRadiusy * sin(dblAngle) + ptCenter.y + 0.5);
      dblAngle += dblDiff;
   }
}

Инициализируйте m_clrFillColor. Выберите зеленый как заданный по умолчанию цвет и добавьте строку ниже в CPolyCtl конструктор в файле PolyCtl.h:

m_clrFillColor = RGB(0, 0xFF, 0);

Конструктор теперь должен выглядеть следующим образом:

CPolyCtl()
{
   m_nSides = 3;
   m_clrFillColor = RGB(0, 0xFF, 0);
}

Дальше соберите снова элемент управления. Откройте ActiveX Control Test Container и вставьте элемент управления. Вы должны видеть зеленый треугольник внутри круга.

Пробуйте изменить число сторон. Чтобы изменять свойство в двойном (dual) интерфейсе из Test Container используйте Invoke Methods:
1.В Test Container щелкните Invoke Methods в Control меню. Диалоговое окно Invoke Method появиться.
2.Выберите PropPut версию свойства Sides из Method Name.
3.Напечатайте 5 в окне редактирования Parameter Value, нажмите Set Value и щелкните по Invoke.

5_1.gif (5967 b)

Обратите внимание что элемент управления не изменяется. Что же неправильно? Хотя Вы изменил число сторон устанавливая m_nSides переменную, Вы не заставляли элемент управления повторно перерисовываться. Если Вы переключись на другое приложение и затем вернетесь обратно чтобы проверить контейнер, Вы увидите что элемент управления повторно окрашен и теперь имеет правильное число сторон.Чтобы исправить эту проблему Вы должны добавить обращение к функции FireViewChange которая определена в IViewObjectExImpl после того как Вы устанавливаете число сторон. Если элемент управления выполняется в собственном окне, FireViewChange вызовет InvalidateRect API. Если элемент управления выполняет без своего окна, InvalidateRect метод будет вызван из интерфейса контейнера.

Новый put_Sides метод следующий:

STDMETHODIMP CPolyCtl::put_Sides(short newVal)
{
   if (newVal > 2 && newVal < 101)
   {
      m_nSides = newVal;
      FireViewChange();
      return S_OK;
   }
   else
      return Error(_T("Shape must have between 3 and 100 sides"));
}

После того, как вы добавили FireViewChange соберите элемент управления снова. На сей раз когда Вы изменяете число сторон и щелкаете Invoke, Вы должны немендленно видеть изменения.

Hosted by uCoz